/*
 * lfs util functions
 *
 * Copyright (c) 2017, Arm Limited. All rights reserved.
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include "gd32w51x.h"
#include "stdio.h"
#include "stdint.h"
#include "DevicesFlash.h"
#include "lfs.h"
#include "lfs_util.h"

// Only compile if user does not provide custom config
#ifndef LFS_CONFIG


// Software CRC implementation with small lookup table
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
    static const uint32_t rtable[16] = {
        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
    };

    const uint8_t *data = buffer;

    for (size_t i = 0; i < size; i++) {
        crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
        crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
    }

    return crc;
}


#endif


// Read a region in a block. Negative error codes are propogated
// to the user.
int iLittlefsRomRead(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
{
    int ret = LFS_ERR_OK;

    ret = cFlashReadDatas(FLASH_LITTLEFS_ADDR + block * c->block_size + off, (uint8_t *)buffer, size);

    return ret;
}

// Program a region in a block. The block must have previously
// been erased. Negative error codes are propogated to the user.
// May return LFS2_ERR_CORRUPT if the block should be considered bad.
int iLittlefsRomProg(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
{
    int ret = LFS_ERR_OK;

    ret = cFlashWriteDatas(FLASH_LITTLEFS_ADDR + block * c->block_size + off, (uint8_t *)buffer, size);

    return ret;
}

// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
// are propogated to the user.
// May return LFS2_ERR_CORRUPT if the block should be considered bad.
int iLittlefsRomErase(const struct lfs_config *c, lfs_block_t block)
{
    return LFS_ERR_OK;
}

// Sync the state of the underlying block device. Negative error codes are propogated to the user.
int iLittlefsRomSync(const struct lfs_config *c)
{
    return LFS_ERR_OK;
}


/* MCU内部FLASH操作句柄 configuration of the filesystem is provided by this struct */
struct lfs_config g_LittleFSRomCfg = {
    // block device operations
    .read  = iLittlefsRomRead,
    .prog  = iLittlefsRomProg,
    .erase = iLittlefsRomErase,
    .sync  = iLittlefsRomSync,

    // block device configuration
    .read_size = 1024 * 16,
    .prog_size = 1024 * 16,
    .block_size = 1024 * 16,
    .block_count = 1024 * 1024 / (1024 * 16),
    .block_cycles = 100,
    .cache_size = 4096,
    .lookahead_size = 4096,
};
